home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TeX 1995 July
/
TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO
/
macros
/
latex209
/
contrib
/
textyl
/
psrc
/
textyl.pas.ad
< prev
next >
Wrap
Text File
|
1993-11-07
|
30KB
|
1,001 lines
* given unit-radius. Scale those points to fit the desired radius
*)
procedure defineCircleCpts (rad : ScaledPts; centx, centy : ScaledPts;
var CircleCpt : ControlPoints;
var numpts : integer);
const UnitRadius = 16777216; (* TWO24 scaledpts *)
var ratio : real;
begin
if (rad = 0) then
begin
complain (ERRBAD);
writeln(logfile,'Error in fig#',pgfigurenum:0,' on page ',currpagenum:0);
writeln(logfile,'Zero length radius for circle! Setting to 1 sp');
rad := 1;
end;
ratio := float(rad) / float(UnitRadius);
numpts := 16;
CircleCpt[1,1] := round (ratio * 16777216.00000) + centx;
CircleCpt[1,2] := 0 + centy; {round (ratio * 0.00000)}
CircleCpt[2,1] := round (ratio * 15500126.47492) + centx;
CircleCpt[2,2] := round (ratio * 6420362.60441) + centy;
CircleCpt[3,1] := round (ratio * 11863283.20303) + centx;
CircleCpt[3,2] := round (ratio * 11863283.20303) + centy;
CircleCpt[4,1] := round (ratio * 6420362.60441) + centx;
CircleCpt[4,2] := round (ratio * 15500126.47492) + centy;
CircleCpt[5,1] := 0 + centx; {round (ratio * -0.00000) }
CircleCpt[5,2] := round (ratio * 16777216.00000) + centy;
CircleCpt[6,1] := round (ratio * -6420362.60441) + centx;
CircleCpt[6,2] := round (ratio * 15500126.47492) + centy;
CircleCpt[7,1] := round (ratio * -11863283.20303) + centx;
CircleCpt[7,2] := round (ratio * 11863283.20303) + centy;
CircleCpt[8,1] := round (ratio * -15500126.47492) + centx;
CircleCpt[8,2] := round (ratio * 6420362.60441) + centy;
CircleCpt[9,1] := round (ratio * -16777216.00000) + centx;
CircleCpt[9,2] := 0 + centy; {round (ratio * -0.00000)}
CircleCpt[10,1] := round (ratio * -15500126.47492) + centx;
CircleCpt[10,2] := round (ratio * -6420362.60441) + centy;
CircleCpt[11,1] := round (ratio * -11863283.20303) + centx;
CircleCpt[11,2] := round (ratio * -11863283.20303) + centy;
CircleCpt[12,1] := round (ratio * -6420362.60441) + centx;
CircleCpt[12,2] := round (ratio * -15500126.47492) + centy;
CircleCpt[13,1] := 0 + centx; {round (ratio * 0.00000) }
CircleCpt[13,2] := round (ratio * -16777216.00000) + centy;
CircleCpt[14,1] := round (ratio * 6420362.60441) + centx;
CircleCpt[14,2] := round (ratio * -15500126.47492) + centy;
CircleCpt[15,1] := round (ratio * 11863283.20303) + centx;
CircleCpt[15,2] := round (ratio * -11863283.20303) + centy;
CircleCpt[16,1] := round (ratio * 15500126.47492) + centx;
CircleCpt[16,2] := round (ratio * -6420362.60441) + centy;
(* create the pre-list phantom *)
CircleCpt[0,1] := CircleCpt[16,1];
CircleCpt[0,2] := CircleCpt[16,2];
end;
{---------------------------------------------------------------}
(* compute control points for an arc going from startangle to
* stopangle, centered at (centx, centy)
*)
procedure definearcpts (rad : ScaledPts; centx, centy : ScaledPts;
startang, stopang : integer;
var cpts : ControlPoints;
var nknots : integer);
var n : integer;
a, b, curr, delta: real;
i : integer;
begin
a := startang * DEGTORAD;
b := stopang * DEGTORAD;
n := 16;
if (a > b) then
begin
a := a - (2 * PI);
end;
delta := abs(b - a) / n;
if (a = b) then
begin
complain (ERRNOTBAD);
writeln(logfile,'Error in compute arc points:: should be a circle');
end;
curr := a;
i := 1;
while ((curr <= b)) do
begin (* make arc about (centx,centy) *)
cpts[i,1] := round (rad * cos (curr)) + centx;
cpts[i,2] := round (rad * sin (curr)) + centy;
i := i + 1;
curr := curr + delta;
end; (* while *)
(* go one point beyond --
* around the arc so that we can have good smoothness
* for this phantom point
*)
cpts[i,1] := round (rad * cos (b + delta)) + centx;
cpts[i,2] := round (rad * sin (b + delta)) + centy;
(* and one phantom point before the list *)
cpts[0,1] := round (rad * cos (a - delta)) + centx;
cpts[0,2] := round (rad * sin (a - delta)) + centy;
nknots := i-1;
end;
(* &&Module spline.p *)
(*
Procedures below may make free use of the global variables
arrayXY [list of control points]
pointmatrix [list of spline segments]
knot [list of spline knots]
catrommtx [matrix for Catmull-Rom splines]
bsplmtx [matrix for B-splines]
lastPoint, intervals
*)
{-----------------------------------------------------}
function max (a, b: integer):integer;
begin
if (a > b) then
max := a
else
max := b;
end;
{-----------------------------------------------------}
function min (a, b: integer):integer;
begin
if (a < b) then
min := a
else
min := b;
end;
{---------------------------------------------------------------------}
(* initialize the Catmull-Rom basis matrix *)
procedure initcrmatrix;
begin
catrommtx[1,1] := -0.5; catrommtx[1,2] := 1.5;
catrommtx[1,3] := -1.5; catrommtx[1,4] := 0.5;
catrommtx[2,1] := 1.0; catrommtx[2,2] := -2.5;
catrommtx[2,3] := 2.0; catrommtx[2,4] := -0.5;
catrommtx[3,1] := -0.5; catrommtx[3,2] := 0.0;
catrommtx[3,3] := 0.5; catrommtx[3,4] := 0.0;
catrommtx[4,1] := 0.0; catrommtx[4,2] := 1.0;
catrommtx[4,3] := 0.0; catrommtx[4,4] := 0.0;
end;
{-----------------------------------------------------}
procedure initbsplmatrix;
begin
bsplmtx[1,1] := -1.0/6.0; bsplmtx[1,2] := 0.5;
bsplmtx[1,3] := -0.5; bsplmtx[1,4] := 1.0/6.0;
bsplmtx[2,1] := 0.5; bsplmtx[2,2] := -1.0;
bsplmtx[2,3] := 0.5; bsplmtx[2,4] := 0.0;
bsplmtx[3,1] := -0.5; bsplmtx[3,2] := 0.0;
bsplmtx[3,3] := 0.5; bsplmtx[3,4] := 0.0;
bsplmtx[4,1] := 1.0/6.0; bsplmtx[4,2] := 2.0/3.0;
bsplmtx[4,3] := 1.0/6.0; bsplmtx[4,4] := 0.0;
end;
{--------------------------------------------------------}
(* init the Cardinal Spline Matrix *)
procedure initcardmatrix;
begin
cardmtx[1,1] := -1.0; cardmtx[1,2] := 1.0;
cardmtx[1,3] := -1.0; cardmtx[1,4] := 1.0;
cardmtx[2,1] := 2.0; cardmtx[2,2] := -2.0;
cardmtx[2,3] := 1.0; cardmtx[2,4] := -1.0;
cardmtx[3,1] := -1.0; cardmtx[3,2] := 0.0;
cardmtx[3,3] := 1.0; cardmtx[3,4] := 0.0;
cardmtx[4,1] := 0.0; cardmtx[4,2] := 1.0;
cardmtx[4,3] := 0.0; cardmtx[4,4] := 0.0;
end;
{--------------------------------------------------------}
procedure initallspline;
begin
initcrmatrix;
initbsplmatrix;
initcardmatrix;
end;
{-----------------------------------------------------}
procedure matXvector (var m: Fourby4Matrix; (* IN *)
var v: Oneby4Vector; (* IN *)
var result: Oneby4Vector); (* OUT *)
var t: Oneby4Vector;
begin
t[1] := v[1]*m[1,1] + v[2]*m[1,2] + v[3]*m[1,3] + v[4]*m[1,4];
t[2] := v[1]*m[2,1] + v[2]*m[2,2] + v[3]*m[2,3] + v[4]*m[2,4];
t[3] := v[1]*m[3,1] + v[2]*m[3,2] + v[3]*m[3,3] + v[4]*m[3,4];
t[4] := v[1]*m[4,1] + v[2]*m[4,2] + v[3]*m[4,3] + v[4]*m[4,4];
result[1] := t[1]; result[2] := t[2];
result[3] := t[3]; result[4] := t[4];
end;
{-----------------------------------------------------}
(* actually the dot-product *)
function vecXvec (var v1, v2: Oneby4Vector) : real;
begin
vecXvec := v1[1]*v2[1] + v1[2]*v2[2] + v1[3]*v2[3] + v1[4]*v2[4];
end;
{------------------------------------------------------}
(* basXctl is the pre-computed BasisMatrix times the control-point vector *)
function splinePosition (var basXctl : Oneby4Vector; (* IN *)
t : real ) : real;
var tvect : Oneby4Vector; { vector of t values for spline matrix}
begin
tvect[4] := 1.0;
tvect[3] := t;
tvect[2] := t * t;
if (tvect[2] <= MINREAL) then
begin (* avoid underflow problems *)
tvect[2] := 0.0;
end;
tvect[1] := t * tvect[2]; (* t^3 *)
splinePosition := vecXvec (tvect, basXctl);
end;
{-------------------------------------------------}
function TwoToThe (n : integer) : integer;
label 78;
var i : integer;
tmp : integer;
begin
tmp := 1;
if (n <= 0) then
goto 78;
if (n < 6) then
begin
case n of
1 : tmp := 2;
2 : tmp := 4;
3 : tmp := 8;
4 : tmp := 16;
5 : tmp := 32;
end; (* case *)
end (* if *)
else
begin
tmp := 32;
for i := 6 to n do
tmp := tmp * 2;
end;
78:
TwoToThe := tmp;
end;
{------------------------------------------------------}
function distance (x0, y0, x1, y1 : real) : real;
var res : real;
begin
res := sqrt ( (x1 - x0)*(x1 - x0) + (y1 - y0)*(y1 - y0));
distance := res;
end;
{------------------------------------------------------}
(* compute the number of subdivisions for this span.
We do this by a quadrature method and a simple linear-distance
metric. This is not optimal in the number of subdivisions actually
required, but is computationally efficient and accurate to the
nearest power of 2 .
*)
function numsubdivisions (var XtimesBas, YtimesBas : Oneby4Vector;
resolution : ScaledPts): integer;
var n : integer;
d : integer;
t : real;
x0, y0, xt, yt : real;
begin
x0 := splinePosition (XtimesBas, 0.0);
y0 := splinePosition (YtimesBas, 0.0);
t := 1.0;
n := 0;
xt := splinePosition (XtimesBas, t);
yt := splinePosition (YtimesBas, t);
while ((round (distance (x0, y0, xt, yt)) > resolution) or
(n < 1)) do
begin
t := t / 2.0; (* perform the quadrature *)
n := n + 1;
xt := splinePosition (XtimesBas, t);
yt := splinePosition (YtimesBas, t);
end; (* while *)
numsubdivisions := TwoToThe (n);
end;
{------------------------------------------------------------------------}
(* compute new control vertices such that the resulting spline
* will interpolate through the old control points.
* This will work as long as the actual arc length
* between consecutive nodes does not vary from span to span.
* The method is noted in Wu and Abel's CACM 20(10) Oct 77 paper
* but the actual working method is from
* Barsky and Greenberg's paper in
* CG&IP 14(3) Nov 1980 pp.203-226
*)
procedure invertsplvertices (numpts : integer;
isclosed : boolean;
var xys : ControlPoints); (* INOUT *)
var i : integer;
beta, Xrprime, Yrprime : array[0..MAXCTLPTS] of real;
tempxys : ControlPoints;
begin
(* compute the values of beta *)
beta[1] := 0.25;
for i := 2 to numpts + 1 do
beta[i] := 1.0 / (4.0 - beta[i - 1]);
(* and the r primes from the original vertices *)
Xrprime[1] := beta[1] * xys[1,1] * 5.0;
Yrprime[1] := beta[1] * xys[1,2] * 5.0;
for i := 2 to numpts -1 do
begin
Xrprime[i] := beta[i] * (6.0 * xys[i,1] - Xrprime[i - 1]);
Yrprime[i] := beta[i] * (6.0 * xys[i,2] - Yrprime[i - 1]);
end; (* for *)
Xrprime[numpts] := beta[numpts] * (5.0 * xys[numpts,1] - Xrprime[numpts - 1]);
Yrprime[numpts] := beta[numpts] * (5.0 * xys[numpts,2] - Yrprime[numpts - 1]);
(* Now perform the back-substitution from the bottom up *)
tempxys[numpts,1] := round (Xrprime[numpts]);
tempxys[numpts,2] := round (Yrprime[numpts]);
for i := numpts - 1 downto 1 do
begin
tempxys[i,1] := round (Xrprime[i] - beta[i] * tempxys[i + 1, 1]);
tempxys[i,2] := round (Yrprime[i] - beta[i] * tempxys[i + 1, 2]);
end;
if (isclosed) then
begin
(* at this point, we've probably been through one control-point
* adjustment, so let's not muck it up
*)
tempxys[numpts+1,1] := tempxys[1,1];
tempxys[numpts+1,2] := tempxys[1,2];
tempxys[numpts+2,1] := tempxys[2,1];
tempxys[numpts+2,2] := tempxys[2,2];
tempxys[0,1] := tempxys[numpts,1];
tempxys[0,2] := tempxys[numpts,2];
(* copy them back *)
for i := 0 to (numpts+2) do
begin
xys[i,1] := tempxys[i,1];
xys[i,2] := tempxys[i,2];
end;
end (* closed *)
else
begin
(* copy back *)
for i := 2 to numpts -1 do
begin
xys[i,1] := tempxys[i,1];
xys[i,2] := tempxys[i,2];
end;
end; (* open*)
end;
{-----------------------------------------------------}
(* adjust the list of control points so that we can use
* it for B-spline interpolation.
* Add any "phantom" vertices necessary so that the end
* conditions will be correct for interpolation
*)
procedure Bctlptadjust (isclosed : boolean; isarc : boolean;
var n: integer; (* INOUT *)
var xys: ControlPoints; (* INOUT *)
var thx: ThickAryType); (* INOUT *)
var j : integer;
tmp : ControlPoints;
tmpthx : ThickAryType;
begin (* ctlpt adjust*)
if (isclosed) then
begin
(* here, we have to supply the last 'real' point for the user,
and add three phantoms-- one before, and two after *)
if (n = 2) then
begin
complain (ERRBAD);
writeln(logfile,'A closed spline requires more than 2 control points ');
writeln(logfile,'making a temporary fix in order to continue...');
xys[3,1] := xys[1,1];
xys[3,2] := xys[1,2];
end;
for j := 1 to (n) do
begin
tmp[j, 1] := xys[j, 1];
tmp[j, 2] := xys[j, 2];
tmpthx[j] := thx[j];
end;
(* Now take care of the 'phantom' vertices *)
tmp[n+1, 1] := xys[1, 1];
tmp[n+1, 2] := xys[1, 2];
tmpthx[n+1] := thx[1];
tmp[n+2, 1] := xys[2, 1];
tmp[n+2, 2] := xys[2, 2];
tmpthx[n+2] := thx[2];
tmp[n+3, 1] := xys[3, 1];
tmp[n+3, 2] := xys[3, 2];
tmpthx[n+3] := thx[3];
if (not isarc) then
begin
tmp[0,1] := xys[n, 1]; (* wrap around to the real last point *)
tmp[0,2] := xys[n, 2];
tmpthx[0] := thx[n];
end
else
begin
tmp[0,1] := xys[0,1];
tmp[0,2] := xys[0,2];
tmpthx[0] := thx[0];
end;
n := n + 1; (* we supplied the 'last' point for the user *)
for j := 0 to n+2 do
begin
xys[j,1] := tmp[j,1];
xys[j,2] := tmp[j,2];
thx[j] := tmpthx[j];
end; (* for *)
end (* if closed *)
else
begin (* OPEN SPLINE *)
if (not isarc) then
begin
tmp[0,1] := 2 * xys[1, 1] - xys[2,1];
tmp[0,2] := 2 * xys[1, 2] - xys[2,2];
end
else
begin
tmp[0,1] := xys[0,1];
tmp[0,2] := xys[0,2];
end;
tmpthx[0] := thx[1];
for j := 1 to (n) do
begin
tmp[j, 1] := xys[j, 1];
tmp[j, 2] := xys[j, 2];
tmpthx[j] := thx[j];
end;
tmp[n+1, 1] := 2 * xys[n, 1] - xys[n-1,1];
tmp[n+1, 2] := 2 * xys[n, 2] - xys[n-1,2];
tmpthx[n+1] := thx[n];
tmp[n+2, 1] := tmp[n+1, 1];
tmp[n+2, 2] := tmp[n+1, 2];
tmpthx[n+2] := thx[n];
for j := 0 to n+2 do
begin
xys[j,1] := tmp[j,1];
xys[j,2] := tmp[j,2];
thx[j] := tmpthx[j];
end; (* for *)
end; (* if open *)
end;
{-----------------------------------------------------}
(* adjust the list of control points so that we can use
* it for simple Catmull-Rom spline interpolation.
* Add any "phantom" vertices necessary so that the end
* conditions will be correct for interpolation
*)
procedure CRctlptadjust (isclosed : boolean; isarc : boolean;
var n: integer; (* INOUT *)
var xys: ControlPoints; (* INOUT *)
var thx: ThickAryType); (* INOUT *)
var j : integer;
tmp : ControlPoints;
tmpthx : ThickAryType;
begin (* ctlpt adjust*)
if (isclosed) then
begin
(* here, we have to supply the last 'real' point for the user,
and add three phantoms-- one before, and two after *)
if (n = 2) then
begin
complain (ERRBAD);
writeln(logfile,'A closed spline requires more than 2 control points ');
writeln(logfile,'making a temporary fix in order to continue...');
xys[3,1] := xys[1,1];
xys[3,2] := xys[1,2];
end;
for j := 1 to (n) do
begin
tmp[j, 1] := xys[j, 1];
tmp[j, 2] := xys[j, 2];
tmpthx[j] := thx[j];
end;
(* the phantom vertices *)
tmp[n+1, 1] := xys[1, 1];
tmp[n+1, 2] := xys[1, 2];
tmpthx[n+1] := thx[1];
tmp[n+2, 1] := xys[2, 1];
tmp[n+2, 2] := xys[2, 2];
tmpthx[n+2] := thx[2];
tmp[n+3, 1] := xys[3, 1];
tmp[n+3, 2] := xys[3, 2];
tmpthx[n+3] := thx[3];
if (not isarc) then
begin
tmp[0,1] := xys[n, 1]; (* wrap around to the real last point *)
tmp[0,2] := xys[n, 2];
tmpthx[0] := thx[n];
end
else
begin
tmp[0,1] := xys[0,1];
tmp[0,2] := xys[0,2];
tmpthx[0] := thx[0];
end;
n := n + 1; (* we supplied the 'last' point for the user *)
for j := 0 to n+2 do
begin
xys[j,1] := tmp[j,1];
xys[j,2] := tmp[j,2];
thx[j] := tmpthx[j];
end; (* for *)
end (* if closed *)
else
begin (* OPEN SPLINE *)
if (not isarc) then
begin
tmp[0,1] := xys[1, 1]; (* double the first point *)
tmp[0,2] := xys[1, 2];
end
else
begin
tmp[0,1] := xys[0,1];
tmp[0,2] := xys[0,2];
end;
tmpthx[0] := thx[1];
for j := 1 to (n) do
begin
tmp[j, 1] := xys[j, 1];
tmp[j, 2] := xys[j, 2];
tmpthx[j] := thx[j];
end;
tmp[n+1, 1] := xys[n, 1]; (* and triple the last *)
tmp[n+1, 2] := xys[n, 2];
tmpthx[n+1] := thx[n];
tmp[n+2, 1] := xys[n, 1];
tmp[n+2, 2] := xys[n, 2];
tmpthx[n+2] := thx[n];
for j := 0 to n+2 do
begin
xys[j,1] := tmp[j,1];
xys[j,2] := tmp[j,2];
thx[j] := tmpthx[j];
end; (* for *)
end; (* if open *)
end; (* ctlpt adjust *)
{----------------------------------------------------------}
procedure interpsplines (splinetype: SplineKind;
isclosed: boolean;
isanArc: boolean;
linepatt : LineStyle;
var basismatrix : Fourby4Matrix; (* IN *)
numctls: integer;
var arrayXY: ControlPoints; (* IN *)
var pointmatrix: SplineSegments; (* OUT *)
varythicks: boolean;
var thickmatrix: ThickAryType; (* IN *)
var TTmatrix: ThickAryType); (* OUT *)
label 32;
var xctl, yctl, { vectors of x, y posits of control points}
wctl : Oneby4Vector; {vector of thicknesses at each ctl pt}
t, incr: real;
Pi: integer; { P sub i }
i, currpt : integer;
theresolution : ScaledPts;
begin (* interp splines*)
if ((not isclosed) and (isanArc)) then
numctls := numctls + 1; (* lie a little *)
case (splinetype) of
BSPL: Bctlptadjust (isclosed, isanArc, numctls, arrayXY, thickmatrix);
CARD,
CATROM: CRctlptadjust (isclosed, isanArc, numctls, arrayXY, thickmatrix);
INTBSPL: begin
if (isclosed) then
begin
Bctlptadjust (true, isanArc, numctls, arrayXY, thickmatrix);
invertsplvertices (numctls, true, arrayXY);
end
else
begin
invertsplvertices (numctls, false, arrayXY);
Bctlptadjust (false, isanArc, numctls, arrayXY, thickmatrix);
end; (* else *)
end; (* Interpolating Bsplines *)
end;
if ((not isclosed) and (isanArc)) then
numctls := numctls - 1; (* UN-lie a little *)
(* this is the scheme:
* val := t-vector * Basis matrix * point matrix
* [t^3 t^2 t 1] * [[Ms]] * [Pi-1 Pi Pi+1 Pi+2]
* where "Pi-1" is "P sub (i-1)", etc.
*
* But we do this in a round about way:
* Point matrix * basis
* then * t-vector will yield the single value
*
* there are certainly faster ways to do this,
* but this is the easiest to understand
*)
currpt := 1;
case linepatt of
solid : theresolution := MAXVECLENsp;
dotted,
dashed,
dotdash : theresolution := 3 * MAXVECLENsp; {###}
end;
for Pi := 1 to (numctls - 1) do
begin
xctl[1] := float(arrayXY[Pi-1, 1]);
xctl[2] := float(arrayXY[Pi, 1]);
xctl[3] := float(arrayXY[Pi+1, 1]);
xctl[4] := float(arrayXY[Pi+2, 1]);
yctl[1] := float(arrayXY[Pi-1, 2]);
yctl[2] := float(arrayXY[Pi, 2]);
yctl[3] := float(arrayXY[Pi+1, 2]);
yctl[4] := float(arrayXY[Pi+2, 2]);
matXvector (basismatrix, xctl, xctl);
matXvector (basismatrix, yctl, yctl);
(* compute the delta-t increment for this segment
based on a metric for subdivision *)
intervals := numsubdivisions (xctl, yctl, theresolution);
if ((linepatt = solid) and (intervals <= 2)) then
intervals := intervals * 2;
incr := 1.0 / intervals;
(* avoid over-flowing the "pointmatrix" *)
if ((currpt + intervals - 1) >= MAXSPLINESEGS) then
begin
complain (ERRREALBAD);
writeln (logfile,'error: Too many spline segments required.');
writeln (logfile,' Reducing the number of control points to get output.');
goto 32;
end;
t := 0.0;
while (t < 0.999999999) do
begin
pointmatrix[currpt, 1] := round (splinePosition (xctl, t));
pointmatrix[currpt, 2] := round (splinePosition (yctl, t));
if (varythicks) then
begin
wctl[1] := float(thickmatrix[Pi-1]);
wctl[2] := float(thickmatrix[Pi ]);
wctl[3] := float(thickmatrix[Pi+1]);
wctl[4] := float(thickmatrix[Pi+2]);
matXvector (catrommtx, wctl, wctl); (* requires using Catmull-Rom *)
TTmatrix[currpt] := round (splinePosition (wctl, t));
end;
t := t + incr;
currpt := currpt + 1;
end; (* while loop *)
end; (* for loop *)
32:
(* the END-condtion *)
pointmatrix[currpt, 1] := round (splinePosition (xctl, 1.0));
pointmatrix[currpt, 2] := round (splinePosition (yctl, 1.0));
if (varythicks) then
begin
wctl[1] := thickmatrix[numctls-2];
wctl[2] := thickmatrix[numctls-1];
wctl[3] := thickmatrix[numctls];
wctl[4] := thickmatrix[numctls+1];
matXvector (catrommtx, wctl, wctl); (* requires using Catmull-Rom *)
TTmatrix[currpt] := round (splinePosition (wctl, 1.0));
end;
lastPoint := currpt;
end; (* interpsplines *)
{----------------------------------------------------------------}
procedure drawSpline (splinetype : SplineKind;
isclosed: boolean;
isanArc: boolean;
patt : LineStyle;
numctls: integer;
var arrayXY: ControlPoints; (* IN *)
var pointmatrix: SplineSegments; (* OUT *)
varythicks: boolean;
var thickmatrix: ThickAryType; (* IN *)
var TTmatrix: ThickAryType); (* OUT *)
begin
lastPoint := 0;
case (splinetype) of
CATROM : interpsplines (splinetype, isclosed, isanArc, patt, catrommtx,
numctls, arrayXY, pointmatrix,
varythicks, thickmatrix, TTmatrix);
CARD : interpsplines (splinetype, isclosed, isanArc, patt, cardmtx,
numctls, arrayXY, pointmatrix,
varythicks, thickmatrix, TTmatrix);
BSPL : interpsplines (splinetype, isclosed, isanArc, patt, bsplmtx,
numctls, arrayXY, pointmatrix,
varythicks, thickmatrix, TTmatrix);
INTBSPL : interpsplines (splinetype, isclosed, isanArc, patt, bsplmtx,
numctls, arrayXY, pointmatrix,
varythicks, thickmatrix, TTmatrix);
end; (*Case *)
end;
(* &&module TeXtyl *)
{----------------------------------------------------------------}
(* rotate a (x,y) point about mx, my *)
procedure ptrotate (var x, y : integer;
mx, my: integer;
angle : real);
var tmpx, tmpy : integer;
cosa, sina : real;
begin
tmpx := x - mx;
tmpy := y - my;
cosa := cos(angle * DEGTORAD);
sina := sin(angle * DEGTORAD);
x := round(tmpx * cosa - tmpy * sina) + mx;
y := round(tmpx * sina + tmpy * cosa) + my;
end;
{----------------------------------------------------------------}
(* transform two line points: scale, rotate and translate
*)
procedure xfmlinepts (var x1, y1, x2, y2 : ScaledPts;
offh, offv : ScaledPts;
midx, midy : ScaledPts;
scalefact : real;
theta : real;
dx, dy : ScaledPts;
sx, sy : real);
begin
if ((sx = 0.0) or (sy = 0.0)) then
begin
complain (ERRBAD);
writeln(logfile,'?? Some scale factor is Zero... continuing anyway');
end;
(* scale about center of item*)
if ((sx <> 1.0) or (sy <> 1.0)) then
begin
x1 := round((x1 - midx) * sx) + midx;
x2 := round((x2 - midx) * sx) + midx;
y1 := round((y1 - midy) * sy) + midy;
y2 := round((y2 - midy) * sy) + midy;
end;
(* rotate if necessary *)
if (theta <> 0.0) then
begin (* rotate about the midpoint *)
ptrotate(x1, y1, midx, midy, theta);
ptrotate(x2, y2, midx, midy, theta);
end;
(* translate *)
x1 := (x1 + round(dx * scalefact) + offh);
x2 := (x2 + round(dx * scalefact) + offh);
y1 := (y1 + round(dy * scalefact) + offv);
y2 := (y2 + round(dy * scalefact) + offv);
end; (* xfmlinepts *)
{----------------------------------------------------------------}
procedure xfmcontpts (var xpts : ControlPoints; xknots : integer;
offh, offv : ScaledPts; midx, midy : ScaledPts;
scalefact : real;
theta : real; dx, dy : ScaledPts; sx, sy : real);
var i : integer;
begin
(* scale about center of item *)
if ((sx <> 1.0) or (sy <> 1.0)) then
for i := 0 to xknots do
begin
xpts[i,1] := round((xpts[i,1] - midx) * sx) + midx;
xpts[i,2] := round((xpts[i,2] - midy) * sy) + midy;
end;
if (theta <> 0.0) then
begin (* rotate about center *)
for i := 0 to xknots do
begin
ptrotate (xpts[i,1], xpts[i,2], midx, midy, theta);
end;
end;
(* translate *)
for i := 0 to xknots do
begin
xpts[i,1] := (xpts[i,1] + round(dx * scalefact) + offh);
xpts[i,2] := (xpts[i,2] + round(dy * scalefact) + offv);
end;
end; (* xfmcontpts *)
{----------------------------------------------------------------}
(* convert into DVI space and offset by H & V *)
procedure dvilinepts (var x1, y1, x2, y2 : ScaledPts;
offh, offv : ScaledPts);
begin
x1 := (x1 + offh);
x2 := (x2 + offh);
y1 := (y1 * (-1) + offv);
y2 := (y2 * (-1) + offv);
end;
{----------------------------------------------------------------}
(* convert into DVI space and offset by H & V *)
procedure dvicontpts (var xpts : ControlPoints; xknots : integer;
offh, offv : ScaledPts);
var i : integer;
begin
for i := 0 to xknots do
begin
xpts[i,1] := (xpts[i,1] + offh);
xpts[i,2] := (xpts[i,2] * (-1) + offv);
end;
end;
{----------------------------------------------------------------}
(* transform all the figure's elements according to the
top-level tranformation requirements in 1st Quadrant space.
then reset the toplevel's xfms.
*)
procedure toplevelxfm (toplev, curfig : pItem; recurlevel : integer);
var pi : pItem;
null1, null2 : ScaledPts;
old1, old2 : ScaledPts;
midx, midy : ScaledPts;
begin
with toplev^ do
begin
midy := (BBty - BBby) div 2;
midx := (BBrx - BBlx) div 2;
end;
pi := curfig^.body^.things; { if recur==0, this is same as toplev }
while (pi <> nil) do
begin
with pi^ do
begin
case (kind) of
Aline : begin
xfmlinepts (lx1, ly1, lx2, ly2, 0, 0, midx, midy, 1.0,
toplev^.figtheta, toplev^.fdx, toplev^.fdy,
toplev^.fsx, toplev^.fsy);
end;
Aspline : begin
xfmcontpts (spts, nsplknots, 0, 0, midx, midy, 1.0,
toplev^.figtheta, toplev^.fdx, toplev^.fdy,
toplev^.fsx, toplev^.fsy);
end;
Attspline : begin
xfmcontpts (ttpts, nttknots, 0, 0, midx, midy, 1.0,
toplev^.figtheta, toplev^.fdx, toplev^.fdy,
toplev^.fsx, toplev^.fsy);
end;
Aarc : begin
null1 := 0; null2 := 0;
old1 := acentx; old2 := acenty;
xfmlinepts (acentx, acenty, null1, null2, 0,0, midx, midy, 1.0,
toplev^.figtheta, toplev^.fdx, toplev^.fdy,
toplev^.fsx, toplev^.fsy);
xfmcontpts (arcpts, narcknots + 1, 0, 0, old1, old2, 1.0,
toplev^.figtheta,
toplev^.fdx + (acentx - old1),
toplev^.fdy + (acenty - old2),
toplev^.fsx, toplev^.fsy);
end;
Alabel : begin
null1 := 0; null2 := 0;
xfmlinepts (labx, laby, null1, null2, 0, 0, midx, midy, 1.0,
toplev^.figtheta, toplev^.fdx, toplev^.fdy,
toplev^.fsx, toplev^.fsy);
end;
Abeam : ; (* not transformable *)
Atieslur: ; (* not transformable *)
Afigure : begin
toplevelxfm (toplev, pi, recurlevel + 1);
end;
end; (* case *)
end; (* with *)
pi := pi^.nextitem;
end; (* while *)
if (recurlevel = 0) then
begin (* reset the toplevel's xfms *)
with toplev^ do
begin
figtheta := 0.0;
fsx := 1.0; fsy := 1.0;
fdx := 0; fdy := 0;
end;
end;
end;
{----------------------------------------------------------------}
function scalefitfactor (actualwid, actualht,
goalwid, goalht: ScaledPts): real;
var sx, sy : real;
begin
sx := goalwid/actualwid;
sy := goalht/actualht;
if (sx < sy) then
scalefitfactor := sx
else
scalefitfactor := sy;
end;
(* ---- The handlers for each primitive ----
* The result of calling each handler is either immediate
* output to the buffer of the commands to produce the
* primitive, OR the primitive gets pushed onto a stack/list
* that defines a current 'figure' (set of prims) for
* output at a later time
*
* Look at linehandle for a basic idea of how the handlers
* work. the others follow pretty closely.
*)
{------------------------------------------------------------}
procedure linehandle (figdepth : integer; scalefact: real;
x1, y1, x2, y2 : ScaledPts;
dvih, dviv : ScaledPts; (* possible dvi-offsets *)
thk : VThickness; vk : VectKind;
patt : LineStyle;
minx, maxx, miny, maxy : ScaledPts;
tx, ty: ScaledPts; sx, sy, r : real);
var midx, midy : ScaledPts;
lineitem : pItem;
begin
midx := (minx + maxx) div 2;
midy := (miny + maxy) div 2;
(* do local primitive -level transformations *)
xfmlinepts (x1, y1, x2, y2, dvih, dviv,
midx, midy, scalefact, r, tx, ty, sx, sy);